package com.csair.irp.job.file.parser.base;

import com.csair.irp.job.common.util.MapUtil;
import com.csair.irp.job.file.parser.manual.ManualTemplateService;
import com.csair.irp.job.file.exception.DataFileException;
import com.csair.irp.job.file.exception.DataOperaterException;
import com.csair.irp.job.file.exception.FileParseException;
import com.csair.irp.job.file.parser.manual.ManualTemplatePO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * txt数据文件一行字符串一个数据对象解析公用流程
 * 如：手动网关txt文件解析
 *
 * @author liaolonglong
 */
public abstract class TxtFileSingleLineDataParser<T> extends BaseFileParser implements DataOperator<T> {

    /**
     * 批量入库的数据量大小
     */
    @Value("${data-file.data-insert-page-size:5000}")
    private int pageSize;

    @Autowired
    private ManualTemplateService manualTemplateService;

    @Override
    protected void doParse(File file, Serializable fileId, Map<Object, Object> params) throws DataFileException {

        String line = null;
        int lineIndex = 0;

        try ( FileInputStream fileInputStream = new FileInputStream(file);
              InputStreamReader reader = new InputStreamReader(fileInputStream, getFileInputStreamReaderCode());
              BufferedReader bufferedReader = new BufferedReader(reader)
        ) {

            //解析每一行数据
            List<T> datas = new ArrayList<>();
            //获取模板信息
            ManualTemplatePO template = manualTemplateService.getByFileBaseinfo(MapUtil.get(params, TASK_BASE_INFO));
            boolean checked = template == null ? true : false;
            int lines = 1;
            //针对头几行数据做特殊处理
            doParseHeader(bufferedReader, lines);

            T tempData = null;
            for (; ; ) {
                line = bufferedReader.readLine();
                if (line == null) {
                    if (datas.size() > 0) {
                        if (tempData != null) {
                            datas.add(tempData);
                        }
                        insertData(datas, fileId);
                    }
                    break;
                }
                lineIndex++;
                //校验模板
                //先从数据库读取模板信息，再指定行数和列数比较内容是否一致;如果模板信息不存在则不校验
                //网关自动对接文件还得走另一套解析校验逻辑
                if (!checked && template != null) {
                    if (lineIndex == template.getColnumIndex()) {
                        if (!line.equals(template.getColnumNames())) {
                            throw new FileParseException(FileManagePO.StateEnum.STATE_ERROR_TEMPLATE);
                        }
                        checked = true;
                    } else {
                        continue;
                    }
                }
                //转换行字符串为数据对象
                tempData = parseLineToData(line, fileId, params);
                if (tempData != null) {
                    datas.add(tempData);
                }

                //分页入库
                if (datas.size() == pageSize) {
                    insertData(datas, fileId);
                    datas.clear();
                }
            }

        } catch (FileParseException e) {
            log.error("数据文件解析异常 fileId={},lineIndex={},line={},path={}", fileId, lineIndex, line, file.getAbsolutePath(), e);
            throw e;
        } catch (DataOperaterException e) {
            log.error("数据入库异常 fileId={},lineIndex={},line={},path={}", fileId, lineIndex, line, file.getAbsolutePath(), e);
            throw e;
        } catch (Exception e) {
            log.error("未知异常 fileId={},lineIndex={},line={},path={}", fileId, lineIndex, line, file.getAbsolutePath(), e);
            throw new DataFileException("未知异常", e);
        }

    }

    /**
     * 处理数据文件头几行，如AET针对第一行数据做校验，还有手动上传的文件一般对第几列做校验
     *
     * @param bufferedReader
     * @param lines
     * @return
     */
    protected void doParseHeader(BufferedReader bufferedReader, int lines) throws DataFileException, IOException {
    }
}
